/************************************************************************
 * <br>
 * <ul>
 * <li>版权所有：唐山弘川科技有限公司 2009－2020</li>
 * <li>创建日期：2009-8-10</li>
 * <li>初始作者：刘川</li>
 * </ul>
 * <ul>
 * <b>修订历史</b>
 * <li>1、</li>
 * </ul>
 ***********************************************************************/
package com.hy.enterprise.framework.persistence.domain.query.internal ;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.cglib.proxy.Factory;

import com.hy.enterprise.framework.lang.LibraRuntimeException;

/**
 * <ul>
 * <li>设计作者：刘川</li>
 * <li>设计日期：2009-8-10</li>
 * <li>设计时间：下午02:35:16</li>
 * <li>设计目的：Libra二次开发平台持久对象工厂</li>
 * </ul>
 * <ul>
 * <b>修订历史</b>
 * <li>1、</li>
 * </ul>
 */
public class LibraPersistentObjectFactory
{
	/**
	 * 当前对象工厂实例
	 */
	public static final LibraPersistentObjectFactory	INSTANCE	=
	                                                                  new LibraPersistentObjectFactory ( ) ;

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午02:39:48</li>
	 * <li>设计目的：</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 * 
	 * @param <T>
	 * @param type
	 * @return
	 */
	@ SuppressWarnings ( "unchecked" )
	private < T > T fakeInstanceForEnum (
	                                      Class < T > type )
	{
		try
		{
			Constructor constructor =
			                          type
			                              .getDeclaredConstructors ( ) [ 0 ] ;
			Method [ ] methods =
			                     constructor
			                                .getClass ( )
			                                .getDeclaredMethods ( ) ;
			for ( Method method : methods )
			{
				if ( method
				           .getName ( )
				           .equals (
				                     "acquireConstructorAccessor" ) )
				{
					method
					      .setAccessible ( true ) ;
					method
					      .invoke (
					                constructor ,
					                new Object [ 0 ] ) ;
				}
			}
			Field [ ] fields =
			                   constructor
			                              .getClass ( )
			                              .getDeclaredFields ( ) ;
			Object constructorAccessor =
			                             null ;
			for ( Field field : fields )
			{
				if ( field
				          .getName ( )
				          .equals (
				                    "constructorAccessor" ) )
				{
					field
					     .setAccessible ( true ) ;
					constructorAccessor =
					                      field
					                           .get ( constructor ) ;
				}
			}
			Method method =
			                constructorAccessor
			                                   .getClass ( )
			                                   .getMethod (
			                                                "newInstance" ,
			                                                new Class [ ]
			                                                {
				                                                Object [ ].class
			                                                } ) ;
			method
			      .setAccessible ( true ) ;

			T value =
			          ( T ) method
			                      .invoke (
			                                constructorAccessor ,
			                                new Object [ ]
			                                {
				                                new Object [ ]
				                                {
				                                        "dummy" ,
				                                        Integer.MAX_VALUE
				                                }
			                                } ) ;
			return value ;
		}
		catch ( IllegalArgumentException illegalArgumentException )
		{
			throw new LibraRuntimeException (
			                                  illegalArgumentException ) ;
		}
		catch ( IllegalAccessException illegalAccessException )
		{
			throw new LibraRuntimeException (
			                                  illegalAccessException ) ;
		}
		catch ( InvocationTargetException invocationTargetException )
		{
			throw new LibraRuntimeException (
			                                  invocationTargetException ) ;
		}
		catch ( SecurityException securityException )
		{
			throw new LibraRuntimeException (
			                                  securityException ) ;
		}
		catch ( NoSuchMethodException noSuchMethodException )
		{
			throw new LibraRuntimeException (
			                                  noSuchMethodException ) ;
		}
	}

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午02:39:21</li>
	 * <li>设计目的：创建指定类型的新的实例</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 * 
	 * @param <T>
	 * @param type
	 * @return
	 */
	@ SuppressWarnings ( "unchecked" )
	public < T > T makeNew (
	                         Class < T > type )
	{
		if ( String.class
		                 .equals ( type ) )
		{
			return ( T ) new String ( ) ;
		}
		else if ( Integer.class
		                       .equals ( type ) )
		{
			return ( T ) new Integer (
			                           42 ) ;
		}
		else if ( Date.class
		                    .equals ( type ) )
		{
			return ( T ) new Date ( ) ;
		}
		else if ( Long.class
		                    .equals ( type ) )
		{
			return ( T ) new Long (
			                        42 ) ;
		}
		else if ( Short.class
		                     .equals ( type ) )
		{
			return ( T ) new Short (
			                         ( short ) 42 ) ;
		}
		else if ( Double.class
		                      .equals ( type ) )
		{
			return ( T ) new Double (
			                          666 ) ;
		}
		else if ( Float.class
		                     .equals ( type ) )
		{
			return ( T ) new Float (
			                         42 ) ;
		}
		else if ( BigInteger.class
		                          .equals ( type ) )
		{
			return ( T ) new BigInteger (
			                              "42" ) ;
		}
		else if ( BigDecimal.class
		                          .equals ( type ) )
		{
			return ( T ) new BigDecimal (
			                              42 ) ;
		}
		else if ( Boolean.class
		                       .equals ( type ) )
		{
			return ( T ) new Boolean (
			                           true ) ;
		}
		else if ( List.class
		                    .isAssignableFrom ( type ) )
		{
			return ( T ) new ArrayList (
			                             0 ) ;
		}
		else if ( Set.class
		                   .isAssignableFrom ( type ) )
		{
			return ( T ) new HashSet (
			                           0 ) ;
		}
		else if ( Map.class
		                   .isAssignableFrom ( type ) )
		{
			return ( T ) new HashMap ( ) ;
		}
		else if ( Enum.class
		                    .isAssignableFrom ( type ) )
		{
			// 返回枚举类型
			return this
			           .fakeInstanceForEnum ( type ) ;
		}
		else
		{
			throw new UnsupportedOperationException (
			                                          "无法创建类型为：["
			                                                  + type
			                                                  + "]的对象。持久类上没有标注@Entity注解" ) ;
		}
	}

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午02:36:18</li>
	 * <li>设计目的：创建与指定实例类型相同的新实例</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 * 
	 * @param <T>
	 * @param instance
	 * @return
	 */
	@ SuppressWarnings ( "unchecked" )
	public < T > T makeNew (
	                         T instance )
	{
		Class < T > type =
		                   ( Class < T > ) instance
		                                           .getClass ( ) ;

		if ( instance instanceof Factory )
		{
			Factory factory =
			                  ( Factory ) instance ;
			return ( T ) factory
			                    .newInstance ( factory
			                                          .getCallbacks ( ) ) ;
		}
		else
		{
			return this
			           .makeNew ( type ) ;
		}
	}
}
